bitkeeper revision 1.1327.2.9 (426f9bfcIjY9QAFCPqWBbFw35vclow)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 27 Apr 2005 14:04:44 +0000 (14:04 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 27 Apr 2005 14:04:44 +0000 (14:04 +0000)
Add support for unix-domain sockets on xend.
Remove some dead code.
Signed-off-by: Mike Wray <mike.wray@hp.com>
33 files changed:
.rootkeys
tools/python/xen/web/SrvBase.py
tools/python/xen/web/SrvDir.py
tools/python/xen/web/defer.py [deleted file]
tools/python/xen/web/httpserver.py
tools/python/xen/web/static.py
tools/python/xen/xend/XendAsynchProtocol.py [deleted file]
tools/python/xen/xend/XendClient.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainConfig.py [deleted file]
tools/python/xen/xend/XendProtocol.py
tools/python/xen/xend/XendRoot.py
tools/python/xen/xend/server/SrvBase.py [deleted file]
tools/python/xen/xend/server/SrvConsole.py
tools/python/xen/xend/server/SrvDaemon.py
tools/python/xen/xend/server/SrvDir.py [deleted file]
tools/python/xen/xend/server/SrvDmesg.py
tools/python/xen/xend/server/SrvDomain.py
tools/python/xen/xend/server/SrvDomainDir.py
tools/python/xen/xend/server/SrvEventDir.py [deleted file]
tools/python/xen/xend/server/SrvNode.py
tools/python/xen/xend/server/SrvRoot.py
tools/python/xen/xend/server/SrvServer.py
tools/python/xen/xend/server/SrvUsbif.py [deleted file]
tools/python/xen/xend/server/SrvVnetDir.py
tools/python/xen/xend/server/SrvXendLog.py
tools/python/xen/xend/server/blkif.py
tools/python/xen/xend/server/channel.py
tools/python/xen/xend/server/console.py
tools/python/xen/xend/server/controller.py
tools/python/xen/xend/server/netif.py
tools/python/xen/xend/server/usbif.py
tools/python/xen/xend/util.py [deleted file]

index 410a16c677cdfe8a018da0df3cb7c21a3d5c8380..2037a998281709904147a97667679bcb6387f391 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 4267a9b1FfCUjW7m9anLERcx9lwhJg tools/python/xen/web/SrvDir.py
 4267a9b1uMXIfzB6-81ZLqMCyTgJmw tools/python/xen/web/__init__.py
 4267a9b1i_zVq36tt2iQejVuR6DGFw tools/python/xen/web/connection.py
-4267a9b1Z2SpO9v-zEDApywETZPDwA tools/python/xen/web/defer.py
 4267a9b1KzSWZwWKYrGRc9bUhow_7Q tools/python/xen/web/http.py
 4267a9b1KWNZhhmZnySe_nLASwO47g tools/python/xen/web/httpserver.py
 4267a9b21miObgEJLAgtLTAKRBK8uQ tools/python/xen/web/protocol.py
 40c9c468Um_qc66OQeLEceIz1pgD5g tools/python/xen/xend/EventServer.py
 40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/python/xen/xend/PrettyPrint.py
 40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/python/xen/xend/Vifctl.py
-4151594bBq8h-bwTfEt8dbBuojMtcA tools/python/xen/xend/XendAsynchProtocol.py
 40c9c4688m3eqnC8fhLu1APm36VOVA tools/python/xen/xend/XendClient.py
 40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/python/xen/xend/XendConsole.py
 40c9c468WnXs6eOUSff23IIGI4kMfQ tools/python/xen/xend/XendDB.py
 40eee3a0sPO-WUu34uHUXOC7HliDGw tools/python/xen/xend/XendDmesg.py
 40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/python/xen/xend/XendDomain.py
-40c9c468bbKq3uC7_fuNUkiMMjArdw tools/python/xen/xend/XendDomainConfig.py
 40c9c4685ykq87_n1kVUbMr9flx9fg tools/python/xen/xend/XendDomainInfo.py
 40f50d99YiiaMI1fZBh1VCDFLD57qg tools/python/xen/xend/XendError.py
 40ffc44eGsgTEY355E3nN4mPLZHhMQ tools/python/xen/xend/XendLogging.py
 40c9c468x191zetrVlMnExfsQWHxIQ tools/python/xen/xend/__init__.py
 40c9c468S2YnCEKmk4ey8XQIST7INg tools/python/xen/xend/encode.py
 4266169ezWIlXSfY50n6HSoVFbosmw tools/python/xen/xend/scheduler.py
-40c9c468DCpMe542varOolW1Xc68ew tools/python/xen/xend/server/SrvBase.py
 40c9c468IxQabrKJSWs0aEjl-27mRQ tools/python/xen/xend/server/SrvConsole.py
 40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/python/xen/xend/server/SrvConsoleDir.py
 40c9c468woSmBByfeXA4o_jGf2gCgA tools/python/xen/xend/server/SrvDaemon.py
-40c9c468EQZJVkCLds-OhesJVVyZbQ tools/python/xen/xend/server/SrvDir.py
 40eee3a0m38EwYXfCSFIjWNwG6jx_A tools/python/xen/xend/server/SrvDmesg.py
 40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/python/xen/xend/server/SrvDomain.py
 40c9c469WzajDjutou3X7FmL9hMf3g tools/python/xen/xend/server/SrvDomainDir.py
-40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/python/xen/xend/server/SrvEventDir.py
 40c9c4694eu5759Dehr4Uhakei0EMg tools/python/xen/xend/server/SrvNode.py
 40c9c469TaZ83ypsrktmPSHLEZiP5w tools/python/xen/xend/server/SrvRoot.py
 40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/python/xen/xend/server/SrvServer.py
-41ee5e8cFlODpYxhBMZqo9ZgGtcHbg tools/python/xen/xend/server/SrvUsbif.py
 40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/python/xen/xend/server/SrvVnetDir.py
 4108f181GtRoD1U9TBuJXMfBbGJwdQ tools/python/xen/xend/server/SrvXendLog.py
 40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/python/xen/xend/server/__init__.py
 4266169eI_oX3YBjwaeC0V-THBRnjg tools/python/xen/xend/server/pciif.py
 41ee5e8dq9NtihbL4nWKjuSLOhXPUg tools/python/xen/xend/server/usbif.py
 40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py
-4189125cL90jKSOcBJ3Vx4nWGiXXvA tools/python/xen/xend/util.py
 40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py
 40cf2937gKQcATgXKGtNeWb1PDH5nA tools/python/xen/xm/create.py
 40f552eariuUSB9TWqCPnDLz5zvxMw tools/python/xen/xm/destroy.py
index b8671ba639e34f89bec1d170d37dc3b2bc2d6aac..099eebc449afbc09d778a10c15509c3f06d57342 100644 (file)
@@ -12,7 +12,6 @@ from xen.xend.XendLogging import log
 import resource
 import http
 import httpserver
-import defer
 
 def uri_pathlist(p):
     """Split a path into a list.
index 25dd7210752d2e1239e5fefa5ec0d01d19c341f8..fb9eb14b3c4aad559918eb2bb5cb144ba3e498f8 100644 (file)
@@ -20,7 +20,7 @@ class SrvConstructor:
 
     def __init__(self, klass):
         """Create a constructor. It is assumed that the class
-        should be imported as 'import klass from klass'.
+        should be imported as 'from xen.xend.server.klass import klass'.
 
         klass  name of its class
         """
diff --git a/tools/python/xen/web/defer.py b/tools/python/xen/web/defer.py
deleted file mode 100644 (file)
index c5f1071..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-
-class Deferred:
-    pass
index 248c4ac528bc5d1e167f0e484ddd28dc54bad2d6..265a75c32d57644c1ac363786df0f835d38b47d7 100644 (file)
@@ -4,6 +4,8 @@ import string
 import socket
 import types
 from urllib import quote, unquote
+import os
+import os.path
 
 from xen.xend import sxp
 from xen.xend.Args import ArgError
@@ -184,7 +186,9 @@ class HttpServerRequest(http.HttpRequest):
 
         @param val: the value
         """
-        if isinstance(val, ThreadRequest):
+        if val is None:
+            return val
+        elif isinstance(val, ThreadRequest):
             return val
         elif self.useSxp():
             self.setHeader("Content-Type", sxp.mime_type)
@@ -316,18 +320,23 @@ class HttpServer:
     def getResource(self, req):
         return self.root.getRequestResource(req)
 
+class UnixHttpServer(HttpServer):
 
-def main():
-    root = SrvDir()
-    a = root.add("a", SrvDir())
-    b = root.add("b", SrvDir())
-    server = HttpServer(root=root)
-    server.run()
-
-if __name__ == "__main__":
-    main()
-        
-        
+    def __init__(self, path=None, root=None):
+        HttpServer.__init__(self, interface='localhost', root=root)
+        self.path = path
         
-            
-
+    def bind(self):
+        pathdir = os.path.dirname(self.path)
+        if not os.path.exists(pathdir):
+            os.makedirs(pathdir)
+        else:
+            try:
+                os.unlink(self.path)
+            except SystemExit:
+                raise
+            except Exception, ex:
+                pass
+        self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        #self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        self.socket.bind(self.path)
index 3bed394e77f9a07757bbedfc6974194fc6c4e2db..430be6cf0d33962398c72fb8ac87e9d169dc52e4 100644 (file)
@@ -24,7 +24,7 @@ class File(Resource):
         if self.type:
             req.setHeader('Content-Type', self.type)
         if self.encoding:
-            rew.setHeader('Content-Encoding', self.encoding)
+            req.setHeader('Content-Encoding', self.encoding)
         req.setHeader('Content-Length', self.getFileSize())
         try:
             io = file(self.filename, "r")
@@ -40,7 +40,6 @@ class File(Resource):
                 io.close()
         except:
             pass
-        return ''
         
 
         
diff --git a/tools/python/xen/xend/XendAsynchProtocol.py b/tools/python/xen/xend/XendAsynchProtocol.py
deleted file mode 100644 (file)
index 6afaf14..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from twisted.protocols import http
-from twisted.internet.protocol import ClientCreator
-from twisted.internet.defer import Deferred
-from twisted.internet import reactor
-
-from XendProtocol import XendClientProtocol, XendRequest
-
-class AsynchXendClient(http.HTTPClient):
-    """A subclass of twisted's HTTPClient to deal with a connection to xend.
-    Makes the request when connected, and delegates handling responses etc.
-    to its protocol (usually an AsynchXendClientProtocol instance).
-    """
-    def __init__(self, protocol, request):
-        self.protocol = protocol
-        self.request = request
-
-    def connectionMade(self):
-        request = self.request
-        url = self.request.url
-        self.sendCommand(request.method, url.fullpath())
-        self.sendHeader('Host', url.location())
-        for (k, v) in request.headers.items():
-            self.sendHeader(k, v)
-        if request.data:
-            self.sendHeader('Content-Length', len(request.data))
-        self.endHeaders()
-        if request.data:
-            self.transport.write(request.data)
-
-    def handleStatus(self, version, status, message):
-        return self.protocol.handleStatus(version, status, message)
-
-    def handleHeader(self, key, val):
-        return self.protocol.handleHeader(key, val)
-
-    def handleResponse(self, data):
-        return self.protocol.handleResponse(data)
-
-class AsynchXendClientProtocol(XendClientProtocol):
-    """An asynchronous xend client. Uses twisted to connect to xend
-    and make the request. It does not block waiting for the result,
-    but sets up a deferred that is called when the result becomes available.
-
-    Uses AsynchXendClient to manage the connection.
-    """
-    def __init__(self):
-        self.err = None
-        self.headers = {}
-
-    def xendRequest(self, url, method, args=None):
-        """Make a request to xend. The returned deferred is called when
-        the result is available.
-        
-        @param url:    xend request url
-        @param method: http method: POST or GET
-        @param args:   request arguments (dict)
-        @return: deferred
-        """
-        request = XendRequest(url, method, args)
-        self.deferred = Deferred()
-        clientCreator = ClientCreator(reactor, AsynchXendClient, self, request)
-        clientCreator.connectTCP(url.host, url.port)
-        return self.deferred
-
-    def callErrback(self, err):
-        if not self.deferred.called:
-            self.err = err
-            self.deferred.errback(err)
-        return err
-
-    def callCallback(self, val):
-        if not self.deferred.called:
-            self.deferred.callback(val)
-        return val
-
-    def handleException(self, err):
-        return self.callErrback(err)
-
-    def handleHeader(self, key, val):
-        self.headers[key.lower()] = val
-
-    def getHeader(self, key):
-        return self.headers.get(key.lower())
-
-    def handleResponse(self, data):
-        if self.err: return self.err
-        val = XendClientProtocol.handleResponse(self, data)
-        if isinstance(val, Exception):
-            self.callErrback(val)
-        else:
-            self.callCallback(val)
-        return val
index e25bababf5ac1ab4a0d2d6a8fe5d1e227423934f..6b29f21e7b35b9a40ff72c0dc1235365fcddb0b8 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 """Client API for the HTTP interface on xend.
 Callable as a script - see main().
-Supports synchronous or asynchronous connection to xend.
+Supports inet or unix connection to xend.
 
 This API is the 'control-plane' for xend.
 The 'data-plane' is done separately. For example, consoles
@@ -15,7 +15,9 @@ import types
 
 import sxp
 import PrettyPrint
-from XendProtocol import XendClientProtocol, SynchXendClientProtocol, XendError
+from XendProtocol import HttpXendClientProtocol, \
+                         UnixXendClientProtocol, \
+                         XendError
 
 DEBUG = 0
 
@@ -32,15 +34,6 @@ def fileof(val):
         return val
     raise XendError('cannot convert value')
 
-# todo: need to sort of what urls/paths are using for objects.
-# e.g. for domains at the moment return '0'.
-# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
-# As an arg, assume abs path is obj uri, otherwise just id.
-
-# Function to convert to full url: Xend.uri(path), e.g.
-# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
-# And should accept urls for ids?
-
 class URL:
     """A URL.
     """
@@ -115,7 +108,7 @@ class Xend:
         @param root:    xend root path on the server
         """
         if client is None:
-            client = SynchXendClientProtocol()
+            client = HttpXendClientProtocol()
         self.client = client
         self.bind(srv, root)
 
@@ -162,9 +155,6 @@ class Xend:
     def vneturl(self, id=''):
         return self.url.relative('vnet/' + str(id))
 
-    def eventurl(self, id=''):
-        return self.url.relative('event/' + str(id))
-
     def xend(self):
         return self.xendGet(self.url)
 
@@ -262,34 +252,33 @@ class Xend:
 
     def xend_domain_maxmem_set(self, id, memory):
         return self.xendPost(self.domainurl(id),
-                             { 'op'     : 'maxmem_set',
-                               'memory' : memory })
+                             { 'op'      : 'maxmem_set',
+                               'memory'  : memory })
+
+    def xend_domain_mem_target_set(self, id, mem_target):
+        val = self.xendPost(self.domainurl(id),
+                            {'op'        : 'mem_target_set',
+                             'target'    : mem_target })
+        return val
 
     def xend_domain_vif_limit(self, id, vif, credit, period):
         return self.xendPost(self.domainurl(id),
-                            { 'op'      : 'vif_credit_limit',
+                            { 'op'      : 'vif_limit_set',
                               'vif'     : vif,
                               'credit'  : credit,
                               'period'  : period })
 
-    def xend_domain_vifs(self, id):
+    def xend_domain_devices(self, id, type):
         return self.xendGet(self.domainurl(id),
-                            { 'op'      : 'vifs' })
+                             {'op'      : 'devices',
+                              'type'    : type })
 
-    def xend_domain_vif(self, id, vif):
+    def xend_domain_device(self, id, type, idx):
         return self.xendGet(self.domainurl(id),
-                            { 'op'      : 'vif',
-                              'vif'     : vif })
-
-    def xend_domain_vbds(self, id):
-        return self.xendGet(self.domainurl(id),
-                            {'op'       : 'vbds'})
-
-    def xend_domain_vbd(self, id, vbd):
-        return self.xendGet(self.domainurl(id),
-                            {'op'       : 'vbd',
-                             'vbd'      : vbd })
-
+                             {'op'      : 'device',
+                              'type'    : type,
+                              'idx'     : idx })
+    
     def xend_domain_device_create(self, id, config):
         return self.xendPost(self.domainurl(id),
                              {'op'      : 'device_create',
@@ -338,63 +327,29 @@ class Xend:
         return self.xendPost(self.vneturl(id),
                               {'op'     : 'delete' })
 
-    def xend_event_inject(self, sxpr):
-        val = self.xendPost(self.eventurl(),
-                             {'op'      : 'inject',
-                              'event'   : fileof(sxpr) })
-
-    def xend_domain_mem_target_set(self, id, mem_target):
-        val = self.xendPost(self.domainurl(id),
-                            {'op'         : 'mem_target_set',
-                             'target'     : mem_target })
-        return val
-
-def getAsynchXendClientProtocol():
-    """Load AsynchXendClientProtocol on demand to avoid the cost.
+def getHttpServer(srv=None):
+    """Create and return a xend client.
     """
-    global AsynchXendClientProtocol
-    try:
-       AsynchXendClientProtocol
-    except:
-        from XendAsynchProtocol import AsynchXendClientProtocol
-    return AsynchXendClientProtocol
+    return Xend(srv=srv, client=XendClientProtocol())
 
-def getAsynchServer():
-    """Load AsynchXendClientProtocol and create an asynch xend client.
-
-    @return asynch Xend
+def getUnixServer(srv=None):
+    """Create and return a unix-domain xend client.
     """
-    getAsynchXendClientProtocol()
-    return Xend(AsynchXendClientProtocol())
+    return Xend(client=UnixXendClientProtocol(srv))
 
-def xendmain(srv, asynch, fn, args):
-    if asynch:
-        getAsynchXendClientProtocol()
-        client = AsynchXendClientProtocol() 
+def xendmain(srv, fn, args, unix=False):
+    if unix:
+        xend = getUnixServer(srv)
     else:
-        client = None
-    xend = Xend(srv=srv, client=client)
+        xend = getHttpServer(srv)
     xend.rc = 0
     try:
         v = getattr(xend, fn)(*args)
+        PrettyPrint.prettyprint(v)
+        return 0
     except XendError, err:
         print 'ERROR:', err
         return 1
-    if asynch:
-        def cbok(val):
-            PrettyPrint.prettyprint(val)
-            reactor.stop()
-        def cberr(err):
-            print 'ERROR:', err
-            xend.rc = 1
-            reactor.stop()
-        v.addCallback(cbok)
-        v.addErrback(cberr)
-        reactor.run()
-        return xend.rc
-    else:
-        PrettyPrint.prettyprint(v)
-        return 0
 
 def main(argv):
     """Call an API function:
@@ -411,16 +366,16 @@ python XendClient.py domain 0
     """
     global DEBUG
     from getopt import getopt
-    short_options = 'x:ad'
-    long_options = ['xend=', 'asynch', 'debug']
+    short_options = 'x:au:d'
+    long_options = ['xend=', 'unix=', 'debug']
     (options, args) = getopt(argv[1:], short_options, long_options)
     srv = None
-    asynch = 0
+    unix = 1
     for k, v in options:
         if k in ['-x', '--xend']:
             srv = v
-        elif k in ['-a', '--asynch']:
-            asynch = 1
+        elif k in ['-u', '--unix']:
+            unix = int(v)
         elif k in ['-d', '--debug']:
             DEBUG = 1
     if len(args):
@@ -431,9 +386,9 @@ python XendClient.py domain 0
         args = []
     if not fn.startswith('xend'):
         fn = 'xend_' + fn
-    sys.exit(xendmain(srv, asynch, fn, args))
+    sys.exit(xendmain(srv, fn, args, unix=unix))
 
 if __name__ == "__main__":
     main(sys.argv)
 else:    
-    server = Xend()
+    server = getUnixServer()
index 334f2f45f613ad479755570b4483088a10c4fde2..b94d4e526492c7fee0f8488d5b3e62b8faf8c81c 100644 (file)
@@ -778,7 +778,7 @@ class XendDomain:
         dominfo = self.domain_lookup(id)
         return dominfo.getDeviceByIndex(type, idx)
 
-    def domain_vif_credit_limit(self, id, vif, credit, period):
+    def domain_vif_limit_set(self, id, vif, credit, period):
         """Limit the vif's transmission rate
         """
         dominfo = self.domain_lookup(id)
@@ -787,40 +787,6 @@ class XendDomain:
             raise XendError("invalid vif")
         return dev.setCreditLimit(credit, period)
         
-    def domain_vif_ls(self, id):
-        """Get list of virtual network interface (vif) indexes for a domain.
-
-        @param id: domain
-        @return: vif indexes
-        """
-        return self.domain_devtype_ls(id, 'vif')
-
-    def domain_vif_get(self, id, vif):
-        """Get a virtual network interface (vif) from a domain.
-
-        @param id: domain
-        @param vif: vif index
-        @return: vif device object (or None)
-        """
-        return self.domain_devtype_get(id, 'vif', vif)
-
-    def domain_vbd_ls(self, id):
-        """Get list of virtual block device (vbd) indexes for a domain.
-
-        @param id: domain
-        @return: vbd indexes
-        """
-        return self.domain_devtype_ls(id, 'vbd')
-
-    def domain_vbd_get(self, id, vbd):
-        """Get a virtual block device (vbd) from a domain.
-
-        @param id: domain
-        @param vbd: vbd index
-        @return: vbd device (or None)
-        """
-        return self.domain_devtype_get(id, 'vbd', vbd)
-
     def domain_shadow_control(self, id, op):
         """Shadow page control.
 
diff --git a/tools/python/xen/xend/XendDomainConfig.py b/tools/python/xen/xend/XendDomainConfig.py
deleted file mode 100644 (file)
index 35db31f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-"""Handler for persistent domain configs.
-
-"""
-
-import sxp
-import XendDB
-import XendDomain
-
-__all__ = [ "XendDomainConfig" ]
-
-class XendDomainConfig:
-
-    dbpath = 'config'
-
-    def __init__(self):
-        self.db = XendDB.XendDB(self.dbpath)
-
-    def domain_config_ls(self, path):
-        return self.db.ls(path)
-
-    def domain_config_create(self, path, sxpr):
-        self.db.save(path, sxpr)
-        pass
-
-    def domain_config_delete(self, path):
-        self.db.delete(path)
-
-    def domain_config_instance(self, path):
-        """Create a domain from a config.
-        """
-        config = self.db.fetch(path)
-        xd = XendDomain.instance()
-        newdom = xd.domain_create(config)
-        return newdom
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = XendDomainConfig()
-    return inst
index db4de7940fcfd312a3712a069857ba1cfafe0483..278173c8f5dd6064decf9bf3fa013e0674d16689 100644 (file)
@@ -1,5 +1,6 @@
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 
+import socket
 import httplib
 import types
 
@@ -122,12 +123,19 @@ class XendClientProtocol:
         """
         raise NotImplementedError()
 
-class SynchXendClientProtocol(XendClientProtocol):
+class HttpXendClientProtocol(XendClientProtocol):
     """A synchronous xend client. This will make a request, wait for
     the reply and return the result.
     """
 
     resp = None
+    request = None
+
+    def makeConnection(self, url):
+        return httplib.HTTPConnection(url.location())
+
+    def makeRequest(self, url, method, args):
+        return XendRequest(url, method, args)
 
     def xendRequest(self, url, method, args=None):
         """Make a request to xend.
@@ -136,8 +144,8 @@ class SynchXendClientProtocol(XendClientProtocol):
         @param method: http method: POST or GET
         @param args:   request arguments (dict)
         """
-        self.request = XendRequest(url, method, args)
-        conn = httplib.HTTPConnection(url.location())
+        self.request = self.makeRequest(url, method, args)
+        conn = self.makeConnection(url)
         if DEBUG: conn.set_debuglevel(1)
         conn.request(method, url.fullpath(), self.request.data, self.request.headers)
         resp = conn.getresponse()
@@ -154,3 +162,29 @@ class SynchXendClientProtocol(XendClientProtocol):
     def getHeader(self, key):
         return self.resp.getheader(key)
 
+class UnixConnection(httplib.HTTPConnection):
+    """Subclass of Python library HTTPConnection that uses a unix-domain socket.
+    """
+
+    def __init__(self, path):
+        httplib.HTTPConnection.__init__(self, 'localhost')
+        self.path = path
+
+    def connect(self):
+        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        sock.connect(self.path)
+        self.sock = sock
+
+class UnixXendClientProtocol(HttpXendClientProtocol):
+    """A synchronous xend client using a unix-domain socket.
+    """
+
+    XEND_PATH_DEFAULT = '/var/lib/xend/xend-socket'
+    
+    def __init__(self, path=None):
+        if path is None:
+            path = self.XEND_PATH_DEFAULT
+        self.path = path
+
+    def makeConnection(self, url):
+        return UnixConnection(self.path)
index c8236a4ecd00454767e19acf71a94cd8ceba3989..f2086735ecec060cb792d4cad8c0f57bd88398c0 100644 (file)
@@ -15,6 +15,7 @@ import sys
 
 import EventServer
 from XendLogging import XendLogging
+from XendError import XendError
 
 # Initial create of the event server.
 eserver = EventServer.instance()
@@ -44,6 +45,9 @@ class XendRoot:
 
     loglevel_default = 'DEBUG'
 
+    """Default for the flag indicating whether xend should run an http server."""
+    xend_http_server_default = 'no'
+
     """Default interface address xend listens at. """
     xend_address_default      = ''
 
@@ -53,7 +57,13 @@ class XendRoot:
     """Default port xend serves events at. """
     xend_event_port_default   = '8001'
 
-    """Default inteface address xend listens at for consoles."""
+    """Default for the flag indicating whether xend should run a unix-domain server."""
+    xend_unix_server_default = 'yes'
+
+    """Default path the unix-domain server listens at."""
+    xend_unix_path_default = '/var/lib/xend/xend-socket'
+
+    """Default interface address xend listens at for consoles."""
     console_address_default   = ''
 
     """Default port xend serves consoles at. """
@@ -157,6 +167,7 @@ class XendRoot:
         logfile = self.get_config_value("logfile", self.logfile_default)
         loglevel = self.get_config_value("loglevel", self.loglevel_default)
         self.logging = XendLogging(logfile, level=loglevel)
+        self.logging.addLogStderr()
 
     def get_logging(self):
         """Get the XendLogging instance.
@@ -218,15 +229,35 @@ class XendRoot:
         """
         return sxp.child_value(self.config, name, val=val)
 
+    def get_config_bool(self, name, val=None):
+        v = self.get_config_value(name, val)
+        if v in ['yes', '1', 'on', 1, True]:
+            return True
+        if v in ['no', '0', 'off', 0, False]:
+            return False
+        raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
+
+    def get_config_int(self, name, val=None):
+        v = self.get_config_value(name, val)
+        try:
+            return int(v)
+        except Exception, ex:
+            raise XendError("invalid xend config %s: expected int: %s" % (name, v))
+
+    def get_xend_http_server(self):
+        """Get the flag indicating whether xend should run an http server.
+        """
+        return self.get_config_bool("xend-http-server", self.xend_http_server_default)
+
     def get_xend_port(self):
         """Get the port xend listens at for its HTTP interface.
         """
-        return int(self.get_config_value('xend-port', self.xend_port_default))
+        return self.get_config_int('xend-port', self.xend_port_default)
 
     def get_xend_event_port(self):
         """Get the port xend listens at for connection to its event server.
         """
-        return int(self.get_config_value('xend-event-port', self.xend_event_port_default))
+        return self.get_config_int('xend-event-port', self.xend_event_port_default)
 
     def get_xend_address(self):
         """Get the address xend listens at for its HTTP and event ports.
@@ -236,6 +267,16 @@ class XendRoot:
         """
         return self.get_config_value('xend-address', self.xend_address_default)
 
+    def get_xend_unix_server(self):
+        """Get the flag indicating whether xend should run a unix-domain server.
+        """
+        return self.get_config_bool("xend-unix-server", self.xend_unix_server_default)
+
+    def get_xend_unix_path(self):
+        """Get the path the xend unix-domain server listens at.
+        """
+        return self.get_config_value("xend-unix-path", self.xend_unix_path_default)
+
     def get_console_address(self):
         """Get the address xend listens at for its console ports.
         This defaults to the empty string which allows all hosts to connect.
@@ -247,7 +288,7 @@ class XendRoot:
     def get_console_port_base(self):
         """Get the base port number used to generate console ports for domains.
         """
-        return int(self.get_config_value('console-port-base', self.console_port_base_default))
+        return self.get_config_int('console-port-base', self.console_port_base_default)
 
     def get_block_script(self, type):
         return self.get_config_value('block-%s' % type, '')
@@ -262,8 +303,7 @@ class XendRoot:
         return self.get_config_value('vif-script', 'vif-bridge')
 
     def get_vif_antispoof(self):
-        v = self.get_config_value('vif-antispoof', 'yes')
-        return v in ['yes', '1', 'on']
+        return self.get_config_bool('vif-antispoof', 'yes')
 
 def instance():
     """Get an instance of XendRoot.
diff --git a/tools/python/xen/xend/server/SrvBase.py b/tools/python/xen/xend/server/SrvBase.py
deleted file mode 100644 (file)
index 9ad1af2..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-from xen.web.SrvBase import *
index 2db502d899513271e59de51569eabf1db1877e1b..233f62b96837c3be50a0d356dcaa5f497fb491a3 100644 (file)
@@ -2,7 +2,7 @@
 
 from xen.xend import sxp
 from xen.xend import XendConsole
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
 
 class SrvConsole(SrvDir):
     """An individual console.
index dcc0e14eef3471a94950868642d1fec8a831d528..74952487530aca9bf773c1f6f8c1f7e33e3f31f7 100644 (file)
@@ -326,10 +326,10 @@ class Daemon:
             self.createFactories()
             self.listenEvent(xroot)
             self.listenChannels()
-            serverthread = SrvServer.create(bridge=1)
+            servers = SrvServer.create()
             self.daemonize()
             print 'running serverthread...'
-            serverthread.start()
+            servers.start()
         except Exception, ex:
             print >>sys.stderr, 'Exception starting xend:', ex
             if DEBUG:
diff --git a/tools/python/xen/xend/server/SrvDir.py b/tools/python/xen/xend/server/SrvDir.py
deleted file mode 100644 (file)
index 05694c2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-from xen.web.SrvBase import *
-from xen.web.SrvDir import *
index f9c3718adda6c702cd06991e4ecf8055c7373599..fbf337712a55977b5a53fb6e055e11528c079249 100644 (file)
@@ -5,7 +5,7 @@ import os
 from xen.xend import sxp
 from xen.xend import XendDmesg
 
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
 
 class SrvDmesg(SrvDir):
     """Xen Dmesg output.
index 27ffb0abfdac502d36bb8192ac878b578fb5d0f5..80fbd97703265fee244ba4cba8aade4d517c0776 100644 (file)
@@ -8,7 +8,7 @@ from xen.xend import XendConsole
 from xen.xend import PrettyPrint
 from xen.xend.Args import FormFn
 
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
 
 class SrvDomain(SrvDir):
     """Service managing a single domain.
@@ -35,10 +35,6 @@ class SrvDomain(SrvDir):
         return val
         
     def op_pause(self, op, req):
-        # Pause doesn't need a thread, but request one for testing.
-        return req.threadRequest(self.do_pause, op, req)
-
-    def do_pause(self, op, req):
         val = self.xd.domain_pause(self.dom.name)
         return val
 
@@ -113,6 +109,31 @@ class SrvDomain(SrvDir):
                      ['memory', 'int']])
         val = fn(req.args, {'dom': self.dom.id})
         return val
+    
+    def op_mem_target_set(self, op, req):
+        fn = FormFn(self.xd.domain_mem_target_set,
+                    [['dom',    'str'],
+                     ['target', 'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_devices(self, op, req):
+        fn = FormFn(self.xd.domain_devtype_ls,
+                    [['dom',    'str'],
+                     ['type',   'str']])
+        val = fn(req.args, {'dom': self.dom.id})
+        return val
+
+    def op_device(self, op, req):
+        fn = FormFn(self.xd.domain_devtype_get,
+                    [['dom',    'str'],
+                     ['type',   'str'],
+                     ['idx',    'int']])
+        val = fn(req.args, {'dom': self.dom.id})
+        if val:
+            return val.sxpr()
+        else:
+            raise XendError("invalid device")
 
     def op_device_create(self, op, req):
         fn = FormFn(self.xd.domain_device_create,
@@ -145,8 +166,8 @@ class SrvDomain(SrvDir):
         val = fn(req.args, {'dom': self.dom.id})
         return val
 
-    def op_vif_credit_limit(self, op, req):
-        fn = FormFn(self.xd.domain_vif_credit_limit,
+    def op_vif_limit_set(self, op, req):
+        fn = FormFn(self.xd.domain_vif_limit_set,
                     [['dom',    'str'],
                      ['vif',    'int'],
                      ['credit', 'int'],
@@ -154,35 +175,6 @@ class SrvDomain(SrvDir):
         val = fn(req.args, {'dom': self.dom.id})
         return val
 
-    def op_vifs(self, op, req):
-        devs = self.xd.domain_vif_ls(self.dom.id)
-        return [ dev.sxpr() for dev in devs ]
-
-    def op_vif(self, op, req):
-        fn = FormFn(self.xd.domain_vif_get,
-                    [['dom', 'str'],
-                     ['vif', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbds(self, op, req):
-        devs = self.xd.domain_vbd_ls(self.dom.id)
-        return [ dev.sxpr() for dev in devs ]
-
-    def op_vbd(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_get,
-                    [['dom', 'str'],
-                     ['vbd', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_mem_target_set(self, op, req):
-        fn = FormFn(self.xd.domain_mem_target_set,
-                    [['dom',    'str'],
-                     ['target', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
     def render_POST(self, req):
         return self.perform(req)
         
index e007baf4d53eef52708fa916fea6748a93c3ef38..6969d87e05787c4b7dae98943d47b54d7b704763 100644 (file)
@@ -11,7 +11,7 @@ from xen.xend.Args import FormFn
 from xen.xend.XendError import XendError
 from xen.xend.XendLogging import log
 
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
 from SrvDomain import SrvDomain
 
 class SrvDomainDir(SrvDir):
diff --git a/tools/python/xen/xend/server/SrvEventDir.py b/tools/python/xen/xend/server/SrvEventDir.py
deleted file mode 100644 (file)
index 02871a4..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xen.xend import sxp
-from xen.xend import EventServer
-from SrvDir import SrvDir
-
-class SrvEventDir(SrvDir):
-    """Event directory.
-    """
-
-    def __init__(self):
-        SrvDir.__init__(self)
-        self.eserver = EventServer.instance()
-
-    def op_inject(self, op, req):
-        eventstring = req.args.get('event')
-        pin = sxp.Parser()
-        pin.input(eventstring)
-        pin.input_eof()
-        sxpr = pin.get_val()
-        self.eserver.inject(sxp.name(sxpr), sxpr)
-        if req.use_sxp:
-            sxp.name(sxpr)
-        else:
-            return '<code>' + eventstring + '</code>'
-        
-    def render_POST(self, req):
-        return self.perform(req)
-
-    def form(self, req):
-        action = req.prePathURL()
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % action)
-        req.write('<button type="submit" name="op" value="inject">Inject</button>')
-        req.write('Event <input type="text" name="event" size="40"><br>')
-        req.write('</form>')
-        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
-                  % action)
-        req.write('<button type="submit" name="op" value="inject">Inject</button>')
-        req.write('Event file<input type="file" name="event"><br>')
-        req.write('</form>')
index 85a8ba47196b1a98369242b0e7059b3e5f3b343c..6768e9b5feaa630c29d1e9871c6bbe80b4f684de 100644 (file)
@@ -2,7 +2,7 @@
 
 import os
 
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
 from xen.xend import sxp
 from xen.xend import XendNode
 from xen.xend.Args import FormFn
index d6d6cb0ae4ea1b795da07ed685bd2dc91c49107e..84ef0081184d50a78f47a0b9597af65e6ba6ca1c 100644 (file)
@@ -2,7 +2,7 @@
 
 from xen.xend import XendRoot
 xroot = XendRoot.instance()
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
 
 class SrvRoot(SrvDir):
     """The root of the xend server.
@@ -16,7 +16,6 @@ class SrvRoot(SrvDir):
         ('node',    'SrvNode'       ),
         ('domain',  'SrvDomainDir'  ),
         ('console', 'SrvConsoleDir' ),
-        ('event',   'SrvEventDir'   ),
         ('vnet',    'SrvVnetDir'    ),
         ]
 
index 43edbe3126674c03b2bfe6859a6f69522d5eadad..bed1d31948044e0b932251b70b18cd43f3fde49c 100644 (file)
 
 from threading import Thread
 
-from xen.web.httpserver import HttpServer
+from xen.web.httpserver import HttpServer, UnixHttpServer
 
-from xen.xend import XendRoot
-xroot = XendRoot.instance()
+from xen.xend import XendRoot; xroot = XendRoot.instance()
 from xen.xend import Vifctl
+from xen.web.SrvDir import SrvDir
+
 from SrvRoot import SrvRoot
-from SrvDir import SrvDir
 
-def create(port=None, interface=None, bridge=0):
-    if port is None:
-        port = xroot.get_xend_port()
-    if interface is None:
-        interface = xroot.get_xend_address()
-    if bridge:
+class XendServers:
+
+    def __init__(self):
+        self.servers = []
+
+    def add(self, server):
+        self.servers.append(server)
+
+    def start(self):
         Vifctl.network('start')
+        for server in self.servers:
+            thread = Thread(target=server.run)
+            thread.start()
+
+def create():
     root = SrvDir()
     root.putChild('xend', SrvRoot())
-    server = HttpServer(root=root, interface=interface, port=port)
-    thread = Thread(name="XendHttpServer", target=server.run)
-    return thread
+    servers = XendServers()
+    if xroot.get_xend_http_server():
+        port = xroot.get_xend_port()
+        interface = xroot.get_xend_address()
+        servers.add(HttpServer(root=root, interface=interface, port=port))
+    if xroot.get_xend_unix_server():
+        path = xroot.get_xend_unix_path()
+        print 'unix path=', path
+        servers.add(UnixHttpServer(path=path, root=root))
+    return servers
diff --git a/tools/python/xen/xend/server/SrvUsbif.py b/tools/python/xen/xend/server/SrvUsbif.py
deleted file mode 100644 (file)
index 5ca73c9..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
-
-from xen.web import http
-
-from xen.xend import sxp
-from xen.xend import XendDomain
-from xen.xend import XendConsole
-from xen.xend import PrettyPrint
-from xen.xend.Args import FormFn
-
-from SrvDir import SrvDir
-
-class SrvDomain(SrvDir):
-    """Service managing a single domain.
-    """
-
-    def __init__(self, dom):
-        SrvDir.__init__(self)
-        self.dom = dom
-        self.xd = XendDomain.instance()
-        self.xconsole = XendConsole.instance()
-
-    def op_configure(self, op, req):
-        """Configure an existing domain.
-        Configure is unusual in that it requires a domain id,
-        not a domain name.
-        """
-        fn = FormFn(self.xd.domain_configure,
-                    [['dom', 'int'],
-                     ['config', 'sxpr']])
-        deferred = fn(req.args, {'dom': self.dom.dom})
-        deferred.addErrback(self._op_configure_err, req)
-        return deferred
-
-    def _op_configure_err(self, err, req):
-        req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
-        return str(err)
-        
-    def op_unpause(self, op, req):
-        val = self.xd.domain_unpause(self.dom.name)
-        return val
-        
-    def op_pause(self, op, req):
-        val = self.xd.domain_pause(self.dom.name)
-        return val
-
-    def op_shutdown(self, op, req):
-        fn = FormFn(self.xd.domain_shutdown,
-                    [['dom', 'str'],
-                     ['reason', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        req.setResponseCode(http.ACCEPTED)
-        req.setHeader("Location", "%s/.." % req.prePathURL())
-        return val
-
-    def op_destroy(self, op, req):
-        fn = FormFn(self.xd.domain_destroy,
-                    [['dom', 'str'],
-                     ['reason', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        req.setHeader("Location", "%s/.." % req.prePathURL())
-        return val
-
-    def op_save(self, op, req):
-        fn = FormFn(self.xd.domain_save,
-                    [['dom', 'str'],
-                     ['file', 'str']])
-        deferred = fn(req.args, {'dom': self.dom.id})
-        deferred.addCallback(self._op_save_cb, req)
-        deferred.addErrback(self._op_save_err, req)
-        return deferred
-
-    def _op_save_cb(self, val, req):
-        return 0
-
-    def _op_save_err(self, err, req):
-        req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
-        return str(err)
-        
-    def op_migrate(self, op, req):
-        fn = FormFn(self.xd.domain_migrate,
-                    [['dom', 'str'],
-                     ['destination', 'str'],
-                     ['live', 'int']])
-        deferred = fn(req.args, {'dom': self.dom.id})
-        print 'op_migrate>', deferred
-        deferred.addCallback(self._op_migrate_cb, req)
-        deferred.addErrback(self._op_migrate_err, req)
-        return deferred
-
-    def _op_migrate_cb(self, info, req):
-        print '_op_migrate_cb>', info, req
-        #req.setResponseCode(http.ACCEPTED)
-        host = info.dst_host
-        port = info.dst_port
-        dom  = info.dst_dom
-        url = "http://%s:%d/xend/domain/%d" % (host, port, dom)
-        req.setHeader("Location", url)
-        print '_op_migrate_cb> url=', url
-        return url
-
-    def _op_migrate_err(self, err, req):
-        print '_op_migrate_err>', err, req
-        req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
-        return str(err)
-
-    def op_pincpu(self, op, req):
-        fn = FormFn(self.xd.domain_pincpu,
-                    [['dom', 'str'],
-                     ['cpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_cpu_bvt_set(self, op, req):
-        fn = FormFn(self.xd.domain_cpu_bvt_set,
-                    [['dom', 'str'],
-                     ['mcuadv', 'int'],
-                     ['warpback', 'int'],
-                     ['warpvalue', 'int'],
-                     ['warpl', 'long'],
-                     ['warpu', 'long']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-    
-    def op_cpu_fbvt_set(self, op, req):
-        fn = FormFn(self.xd.domain_cpu_fbvt_set,
-                    [['dom', 'str'],
-                     ['mcuadv', 'int'],
-                     ['warp', 'int'],
-                     ['warpl', 'int'],
-                     ['warpu', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_maxmem_set(self, op, req):
-        fn = FormFn(self.xd.domain_maxmem_set,
-                    [['dom', 'str'],
-                     ['memory', 'int']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_device_create(self, op, req):
-        fn = FormFn(self.xd.domain_device_create,
-                    [['dom', 'str'],
-                     ['config', 'sxpr']])
-        d = fn(req.args, {'dom': self.dom.id})
-        return d
-
-    def op_device_destroy(self, op, req):
-        fn = FormFn(self.xd.domain_device_destroy,
-                    [['dom', 'str'],
-                     ['type', 'str'],
-                     ['idx', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-                
-    def op_vifs(self, op, req):
-        devs = self.xd.domain_vif_ls(self.dom.id)
-        return [ dev.sxpr() for dev in devs ]
-
-    def op_vif(self, op, req):
-        fn = FormFn(self.xd.domain_vif_get,
-                    [['dom', 'str'],
-                     ['vif', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def op_vbds(self, op, req):
-        devs = self.xd.domain_vbd_ls(self.dom.id)
-        return [ dev.sxpr() for dev in devs ]
-
-    def op_vbd(self, op, req):
-        fn = FormFn(self.xd.domain_vbd_get,
-                    [['dom', 'str'],
-                     ['vbd', 'str']])
-        val = fn(req.args, {'dom': self.dom.id})
-        return val
-
-    def render_POST(self, req):
-        return self.perform(req)
-        
-    def render_GET(self, req):
-        op = req.args.get('op')
-        if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd']:
-            return self.perform(req)
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(self.dom.sxpr(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            #self.ls()
-            req.write('<p>%s</p>' % self.dom)
-            if self.dom.console:
-                cinfo = self.dom.console
-                cid = str(cinfo.console_port)
-                #todo: Local xref: need to know server prefix.
-                req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
-                          % (cid, cid))
-                req.write('<p><a href="%s">Connect to console</a></p>'
-                          % cinfo.uri())
-            if self.dom.config:
-                req.write("<code><pre>")
-                PrettyPrint.prettyprint(self.dom.config, out=req)
-                req.write("</pre></code>")
-            self.form(req)
-            req.write('</body></html>')
-        return ''
-
-    def form(self, req):
-        url = req.prePathURL()
-        req.write('<form method="post" action="%s">' % url)
-        req.write('<input type="submit" name="op" value="unpause">')
-        req.write('<input type="submit" name="op" value="pause">')
-        req.write('</form>')
-
-        req.write('<form method="post" action="%s">' % url)
-        req.write('<input type="submit" name="op" value="destroy">')
-        req.write('<input type="radio" name="reason" value="halt" checked>Halt')
-        req.write('<input type="radio" name="reason" value="reboot">Reboot')
-        req.write('</form>')
-
-        req.write('<form method="post" action="%s">' % url)
-        req.write('<input type="submit" name="op" value="shutdown">')
-        req.write('<input type="radio" name="reason" value="poweroff" checked>Poweroff')
-        req.write('<input type="radio" name="reason" value="halt">Halt')
-        req.write('<input type="radio" name="reason" value="reboot">Reboot')
-        req.write('</form>')
-        
-        req.write('<form method="post" action="%s">' % url)
-        req.write('<br><input type="submit" name="op" value="save">')
-        req.write(' To file: <input type="text" name="file">')
-        req.write('</form>')
-        
-        req.write('<form method="post" action="%s">' % url)
-        req.write('<br><input type="submit" name="op" value="migrate">')
-        req.write(' To host: <input type="text" name="destination">')
-        req.write('<input type="checkbox" name="live" value="1">Live')
-        req.write('</form>')
index 67f7706f449300b16e46eda022e5927e9d11a802..bc5b583b42837b16ed920a84de2f1e3ff6a49440 100644 (file)
@@ -5,7 +5,7 @@ from xen.xend.Args import FormFn
 from xen.xend import PrettyPrint
 from xen.xend import XendVnet
 
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
 
 class SrvVnet(SrvDir):
 
index efb28eb492c379d303dc23f046445b239ef56592..9b8a7dc0e8fc67c724006c047b5e9e5cac2b203f 100644 (file)
@@ -4,7 +4,7 @@ from xen.web import static
 
 from xen.xend import XendRoot
 
-from SrvDir import SrvDir
+from xen.web.SrvDir import SrvDir
 
 class SrvXendLog(SrvDir):
     """Xend log.
index 18e94e336a18cfc3a6f1b77aa52795b18c94eedd..10ce6c9eac156f2c434e524a947d38490c44ba00 100755 (executable)
@@ -425,10 +425,10 @@ class BlkifController(DevController):
     for a domain.
     """
     
-    def __init__(self, dctype, vm, recreate=False):
+    def __init__(self, vm, recreate=False):
         """Create a block device controller.
         """
-        DevController.__init__(self, dctype, vm, recreate=recreate)
+        DevController.__init__(self, vm, recreate=recreate)
         self.backends = {}
         self.backendId = 0
         self.rcvr = None
index 3373f504908e5ab3a8bfdbad32109d636a1ea5f5..d60c206382e6650e98b685c0b351e31c11daba1d 100755 (executable)
@@ -66,6 +66,8 @@ class ChannelFactory:
     def __init__(self):
         """Constructor - do not use. Use the channelFactory function."""
         self.notifier = xu.notifier()
+        # Register interest in all virqs.
+        # Unfortunately virqs do not seem to be delivered.
         self.bind_virq(VIRQ_MISDIRECT)
         self.bind_virq(VIRQ_TIMER)
         self.bind_virq(VIRQ_DEBUG)
@@ -97,6 +99,7 @@ class ChannelFactory:
 
     def main(self):
         """Main routine for the thread.
+        Reads the notifier and dispatches to channels.
         """
         while True:
             if self.thread == None: return
@@ -224,18 +227,23 @@ def channelFactory():
     return inst
 
 class Channel:
+    """Chanel to a domain.
+    Maintains a list of device handlers to dispatch requests to, based
+    on the request type.
+    """
 
     def __init__(self, factory, dom, local_port, remote_port):
         self.factory = factory
         self.dom = int(dom)
-        # Registered devices.
+        # Registered device handlers.
         self.devs = []
-        # Devices indexed by the message types they handle.
+        # Handlers indexed by the message types they handle.
         self.devs_by_type = {}
         self.port = self.factory.createPort(self.dom,
                                             local_port=local_port,
                                             remote_port=remote_port)
         self.closed = False
+        # Queue of waiters for responses to requests.
         self.queue = ResponseQueue(self)
         # Make sure the port will deliver all the messages.
         self.port.register(TYPE_WILDCARD)
@@ -298,11 +306,11 @@ class Channel:
 
 
     def registerDevice(self, types, dev):
-        """Register a device controller.
+        """Register a device message handler.
 
-        @param types: message types the controller handles
+        @param types: message types handled
         @type  types: array of ints
-        @param dev:   device controller
+        @param dev:   device handler
         """
         if self.closed: return
         self.devs.append(dev)
@@ -310,9 +318,9 @@ class Channel:
             self.devs_by_type[ty] = dev
 
     def deregisterDevice(self, dev):
-        """Remove the registration for a device controller.
+        """Remove the registration for a device handler.
 
-        @param dev: device controller
+        @param dev: device handler
         """
         if dev in self.devs:
             self.devs.remove(dev)
@@ -321,16 +329,20 @@ class Channel:
             del self.devs_by_type[ty]
 
     def getDevice(self, type):
-        """Get the device controller handling a message type.
+        """Get the handler for a message type.
 
         @param type: message type
         @type  type: int
         @return: controller or None
-        @rtype:  device controller
+        @rtype:  device handler
         """
         return self.devs_by_type.get(type)
 
     def requestReceived(self, msg):
+        """A request has been received on the channel.
+        Disptach it to the device handlers.
+        Called from the channel factory thread.
+        """
         if DEBUG:
             print 'Channel>requestReceived>', self,
             printMsg(msg)
@@ -340,7 +352,7 @@ class Channel:
         if dev:
             responded = dev.requestReceived(msg, ty, subty)
         elif DEBUG:
-            print "Channel>requestReceived> No device", self,
+            print "Channel>requestReceived> No device handler", self,
             printMsg(msg)
         else:
             pass
@@ -348,6 +360,8 @@ class Channel:
             self.writeResponse(msg)
 
     def writeRequest(self, msg):
+        """Write a request to the channel.
+        """
         if DEBUG:
             print 'Channel>writeRequest>', self,
             printMsg(msg, all=True)
@@ -356,6 +370,8 @@ class Channel:
         return 1
 
     def writeResponse(self, msg):
+        """Write a response to the channel.
+        """
         if DEBUG:
             print 'Channel>writeResponse>', self,
             printMsg(msg, all=True)
@@ -364,6 +380,9 @@ class Channel:
         return 1
 
     def readRequest(self):
+        """Read a request from the channel.
+        Called internally.
+        """
         if self.closed:
             val =  None
         else:
@@ -371,6 +390,9 @@ class Channel:
         return val
         
     def readResponse(self):
+        """Read a response from the channel.
+        Called internally.
+        """
         if self.closed:
             val = None
         else:
@@ -399,6 +421,10 @@ class Channel:
         return self.queue.call(msg, timeout)
 
     def responseReceived(self, msg):
+        """A response has been received, look for a waiter to
+        give it to.
+        Called internally.
+        """
         if DEBUG:
             print 'Channel>responseReceived>', self,
             printMsg(msg)
@@ -407,7 +433,6 @@ class Channel:
     def virq(self):
         self.factory.virq()
 
-
 class Response:
     """Entry in the response queue.
     Used to signal a response to a message.
@@ -463,7 +488,8 @@ class ResponseQueue:
         return r
 
     def response(self, mid, msg):
-        """Process a response.
+        """Process a response - signals any waiter that a response
+        has arrived.
         """
         try:
             self.lock.acquire()
index 339366fa6e36cc1283bf9d224dc535d8f05322a7..ac63703f210fab942f9351c865c92cc0d643e793 100755 (executable)
@@ -326,8 +326,8 @@ class ConsoleController(DevController):
     """Device controller for all the consoles for a domain.
     """
 
-    def __init__(self, dctype, vm, recreate=False):
-        DevController.__init__(self, dctype, vm, recreate=recreate)
+    def __init__(self, vm, recreate=False):
+        DevController.__init__(self, vm, recreate=recreate)
         self.rcvr = None
 
     def initController(self, recreate=False, reboot=False):
index 9343c8b1329d2efed800e14263ba90b8be600d31..9205b2778eac4a60ba12536fcada630019515c40 100755 (executable)
@@ -9,7 +9,7 @@ from messages import msgTypeName, printMsg, getMessageType
 DEBUG = 0
 
 class CtrlMsgRcvr:
-    """Dispatcher class for messages on a control channel.
+    """Utility class to dispatch messages on a control channel.
     Once I{registerChannel} has been called, our message types are registered
     with the channel. The channel will call I{requestReceived}
     when a request arrives if it has one of our message types.
@@ -105,65 +105,32 @@ class CtrlMsgRcvr:
         if self.channel:
             self.channel.deregisterDevice(self)
 
-class DevControllerType:
-    """Abstract class for device controller types.
-    """
-
-    def __init__(self, type):
-        self.type = type
-
-    def getType(self):
-        """Get the device controller type name.
-        """
-        return self.type
-
-    def createDevController(self, vm, recreate=False):
-        """Create a device controller for a domain.
-           Must be implemented in subclass.
-        """
-        raise NotImplementedError()
-
-class SimpleDevControllerType(DevControllerType):
-    """Device controller type that simply wraps a controller
-    class and uses its constructor to create instances.
-    """
-    
-    def __init__(self, type, devControllerClass):
-        DevControllerType.__init__(self, type)
-        self.devControllerClass = devControllerClass
-
-    def createDevController(self, vm, recreate=False):
-        """Create a device controller for a domain.
-        """
-        ctrl = self.devControllerClass(self, vm, recreate=recreate)
-        ctrl.initController(recreate=recreate)
-        return ctrl
-
 class DevControllerTable:
-    """Table of device controller types, indexed by type name.
+    """Table of device controller classes, indexed by type name.
     """
 
     def __init__(self):
-        self.controllerTypes = {}
+        self.controllerClasses = {}
 
-    def getDevControllerType(self, type):
-        return self.controllerTypes.get(type)
+    def getDevControllerClass(self, type):
+        return self.controllerClasses.get(type)
 
-    def addDevControllerType(self, dctype):
-        self.controllerTypes[dctype.getType()] = dctype
-        return dctype
+    def addDevControllerClass(self, klass):
+        self.controllerClasses[klass.getType()] = klass
 
-    def delDevControllerType(self, type):
-        if type in self.controllerTypes:
-            del self.controllerTypes[type]
+    def delDevControllerClass(self, type):
+        if type in self.controllerClasses:
+            del self.controllerClasses[type]
 
     def createDevController(self, type, vm, recreate=False):
-        dctype = self.getDevControllerType(type)
-        if not dctype:
+        klass = self.getDevControllerClass(type)
+        if not klass:
             raise XendError("unknown device type: " + type)
-        return dctype.createDevController(vm, recreate=recreate)
+        return klass.createDevController(vm, recreate=recreate)
 
 def getDevControllerTable():
+    """Singleton constructor for the controller table.
+    """
     global devControllerTable
     try:
         devControllerTable
@@ -171,12 +138,11 @@ def getDevControllerTable():
         devControllerTable = DevControllerTable()
     return devControllerTable
 
-def addDevControllerType(dctype):
-    return getDevControllerTable().addDevControllerType(dctype)
-    
 def addDevControllerClass(name, klass):
-    ty = SimpleDevControllerType(name, klass)
-    return addDevControllerType(ty)
+    """Add a device controller class to the controller table.
+    """
+    klass.name = name
+    getDevControllerTable().addDevControllerClass(klass)
 
 def createDevController(name, vm, recreate=False):
     return getDevControllerTable().createDevController(name, vm, recreate=recreate)
@@ -189,17 +155,29 @@ class DevController:
 
     """
 
-    def __init__(self, dctype, vm, recreate=False):
-        self.dctype = dctype
+    name = None
+
+    def createDevController(klass, vm, recreate=False):
+        """Class method to create a dev controller.
+        """
+        ctrl = klass(vm, recreate=recreate)
+        ctrl.initController(recreate=recreate)
+        return ctrl
+
+    createDevController = classmethod(createDevController)
+
+    def getType(klass):
+        return klass.name
+
+    getType = classmethod(getType)
+
+    def __init__(self, vm, recreate=False):
         self.destroyed = False
         self.vm = vm
         self.deviceId = 0
         self.devices = {}
         self.device_order = []
 
-    def getType(self):
-        return self.dctype.getType()
-
     def getDevControllerType(self):
         return self.dctype
 
@@ -222,6 +200,14 @@ class DevController:
     # Redefinitions must have the same arguments.
 
     def initController(self, recreate=False, reboot=False):
+        """Initialise the controller. Called when the controller is
+        first created, and again after the domain is rebooted (with reboot True).
+        If called with recreate True (and reboot False) the controller is being
+        recreated after a xend restart.
+
+        As this can be a re-init (after reboot) any controller state should
+        be reset. For example the destroyed flag.
+        """
         self.destroyed = False
         if reboot:
             self.rebootDevices()
@@ -229,12 +215,19 @@ class DevController:
     def newDevice(self, id, config, recreate=False):
         """Create a device with the given config.
         Must be defined in subclass.
+        Called with recreate True when the device is being recreated after a
+        xend restart.
 
         @return device
         """
         raise NotImplementedError()
 
     def createDevice(self, config, recreate=False, change=False):
+        """Create a device and attach to its front- and back-ends.
+        If recreate is true the device is being recreated after a xend restart.
+        If change is true the device is a change to an existing domain,
+        i.e. it is being added at runtime rather than when the domain is created.
+        """
         dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate)
         dev.init(recreate=recreate)
         self.addDevice(dev)
@@ -252,7 +245,12 @@ class DevController:
 
     def destroyDevice(self, id, change=False, reboot=False):
         """Destroy a device.
-        May be defined in subclass."""
+        May be defined in subclass.
+
+        If reboot is true the device is being destroyed for a domain reboot.
+
+        The device is not deleted, since it may be recreated later.
+        """
         dev = self.getDevice(id)
         if not dev:
             raise XendError("invalid device id: " + id)
@@ -260,12 +258,18 @@ class DevController:
         return dev
 
     def deleteDevice(self, id, change=True):
+        """Destroy a device and delete it.
+        Normally called to remove a device from a domain at runtime.
+        """
         dev = self.destroyDevice(id, change=change)
         self.removeDevice(dev)
 
     def destroyController(self, reboot=False):
         """Destroy all devices and clean up.
-        May be defined in subclass."""
+        May be defined in subclass.
+        If reboot is true the controller is being destroyed for a domain reboot.
+        Called at domain shutdown.
+        """
         self.destroyed = True
         self.destroyDevices(reboot=reboot)
 
@@ -394,6 +398,13 @@ class Dev:
         """Initialization. Called on initial create (when reboot is False)
         and on reboot (when reboot is True). When xend is restarting is
         called with recreate True. Define in subclass if needed.
+
+        Device instance variables must be defined in the class constructor,
+        but given null or default values. The real values should be initialised
+        in this method. This allows devices to be re-initialised.
+
+        Since this can be called to re-initialise a device any state flags
+        should be reset.
         """
         self.destroyed = False
 
@@ -404,7 +415,7 @@ class Dev:
         pass
 
     def reboot(self):
-        """Reconnect device when the domain is rebooted.
+        """Reconnect the device when the domain is rebooted.
         """
         self.init(reboot=True)
         self.attach()
@@ -435,6 +446,9 @@ class Dev:
         If change is True notify destruction (runtime change).
         If reboot is True the device is being destroyed for a reboot.
         Redefine in subclass if needed.
+
+        Called at domain shutdown and when a device is deleted from
+        a running domain (with change True).
         """
         self.destroyed = True
         pass
index 8c61994cafd255a3324c198fa6bf5d18d9870386..5e3d0d74469d8ff16c1a39ec1eac26bb7ff49784 100755 (executable)
@@ -376,8 +376,8 @@ class NetifController(DevController):
     """Network interface controller. Handles all network devices for a domain.
     """
     
-    def __init__(self, dctype, vm, recreate=False):
-        DevController.__init__(self, dctype, vm, recreate=recreate)
+    def __init__(self, vm, recreate=False):
+        DevController.__init__(self, vm, recreate=recreate)
         self.channel = None
         self.rcvr = None
         self.channel = None
index e529d517617c5cc891e1d0ef4a0d5e47a97a86ea..0c1dd6f63822c435153746143d608f535a3a0adf 100644 (file)
@@ -240,10 +240,10 @@ class UsbifController(DevController):
     for a domain.
     """
     
-    def __init__(self, dctype, vm, recreate=False):
+    def __init__(self, vm, recreate=False):
         """Create a USB device controller.
         """
-        DevController.__init__(self, dctype, vm, recreate=recreate)
+        DevController.__init__(self, vm, recreate=recreate)
         self.backends = {}
         self.backendId = 0
         self.rcvr = None
diff --git a/tools/python/xen/xend/util.py b/tools/python/xen/xend/util.py
deleted file mode 100644 (file)
index e69de29..0000000